package com.zh.note.aop;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.zh.note.annotation.MethodExporter;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 记录接口的url,状态码 参数 耗时信息
 */
@Aspect
@Component
@Slf4j
public class MethodExporterAspect {
    //容器捞鱼，谁带着使用了MethodExporter注解将会触发Around业务逻辑
    @Around("@annotation(com.zh.note.annotation.MethodExporter)")
    public Object methodExporter(ProceedingJoinPoint joinPoint) throws Throwable {
        Object retValue = null;

        long startTime = System.currentTimeMillis();
        System.out.println("-----@Around环绕通知AAA-methodExporter");

        retValue = joinPoint.proceed(); //放行

        long endTime = System.currentTimeMillis();
        long costTime = endTime - startTime;

        //1 获得重载后的方法名
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        //2 确定方法名后获得该方法上面配置的注解标签MyRedisCache
        MethodExporter methodExporterAnnotation = method.getAnnotation(MethodExporter.class);

        if (methodExporterAnnotation != null) {
            //3 获得方法里面的形参信息
            StringBuffer jsonInputParam = new StringBuffer();
            // 获取连接点的参数数组
            Object[] args = joinPoint.getArgs();
            // 创建默认参数名称发现器，用于解析方法参数名称
            DefaultParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
            // 通过方法对象获取参数名称数组
            String[] parameterNames = discoverer.getParameterNames(method);

            for (int i = 0; i < parameterNames.length; i++) {
                jsonInputParam.append(parameterNames[i] + "\t" + args[i].toString() + ";");
            }
            //4 将返回结果retValue序列化
            String jsonResult = null;
            if (retValue != null) {
                jsonResult = new ObjectMapper().writeValueAsString(retValue);
            } else {
                jsonResult = "null";
            }

            log.info("\n方法分析上报中 " + "\n类名方法名:" + joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"
                    + "\n执行耗时:" + costTime
                    + "毫秒" + "\n输入参数:" + jsonInputParam + "" + "\n返回结果:" + jsonResult + "" + "\nover");
            System.out.println("-----@Around环绕通知BBB-methodExporter");
        }

        return retValue;
    }
}

